class MOORA:
    def __init__(self,matrix,weight,q):
        '''

        :param matrix: 决策矩阵
        :param weight: 属性权重
        :param Gangliang: 属性的成本或效益型
        :param Al_title: 备选方案的名称
        :param q:
        '''
        self.matrix_1 = matrix
        self.weight = weight
        self.lines = len(matrix)  # 行
        self.colums = len(matrix[0])  # 列
        Al_title = []
        for i in range(len(matrix)):
            Al_title.append('A' + str(i + 1))
        At_title = []
        for i in range(len(matrix[0])):
            At_title.append('C' + str(i + 1))
        self.Al_title=Al_title
        self.At_title = At_title
        self.q = q

    #区间值广义正交运算法则加法
    def Add(self, a1, a2):
        product1 = pow(
            pow(a1[0][0], self.q) + pow(a2[0][0], self.q) - (pow(a1[0][0], self.q)) * (pow(a2[0][0], self.q)),
            1 / self.q)
        product2 = pow(
            pow(a1[0][1], self.q) + pow(a2[0][1], self.q) - (pow(a1[0][1], self.q)) * (pow(a2[0][1], self.q)),
            1 / self.q)
        product3 = a1[1][0] * a2[1][0]
        product4 = a1[1][1] * a2[1][1]

        a = ([product1, product2], [product3, product4])
        return a

    #区间值广义正交运算法则减法
    def Subtraction(self, a1, a2):
        product1 = a1[0][0] * a2[1][0]
        product2 = a1[0][1] * a2[1][1]
        product3 = pow(
            pow(a1[1][0], self.q) + pow(a2[0][0], self.q) - (pow(a1[1][0], self.q)) * (pow(a2[0][0], self.q)),
            1 / self.q)
        product4 = pow(
            pow(a1[1][1], self.q) + pow(a2[0][1], self.q) - (pow(a1[1][1], self.q)) * (pow(a2[0][1], self.q)),
            1 / self.q)

        a = ([product1, product2], [product3, product4])
        return a

    #区间值广义正交运算法则数乘
    def number_multiplication(self, a1, n):
        product1 = pow(1 - pow(1 - pow(a1[0][0], self.q), n), 1 / self.q)
        product2 = pow(1 - pow(1 - pow(a1[0][1], self.q), n), 1 / self.q)
        product3 = pow(a1[1][0], n)
        product4 = pow(a1[1][1], n)

        a = ([product1, product2], [product3, product4])
        return a

    #区间值广义正交运算法则乘积
    def multiplication(self, a1, a2):
        product1 = a1[0][0] * a2[0][0]
        product2 = a1[0][1] * a2[0][1]
        product3 = pow(
            pow(a1[1][0], self.q) + pow(a2[1][0], self.q) - (pow(a1[1][0], self.q)) * (pow(a2[1][0], self.q)),
            1 / self.q)
        product4 = pow(
            pow(a1[1][1], self.q) + pow(a2[1][1], self.q) - (pow(a1[1][1], self.q)) * (pow(a2[1][1], self.q)),
            1 / self.q)

        a = ([product1, product2], [product3, product4])
        return a

    #区间值广义正交运算法则幂
    def power(self, a1, n):
        product1 = pow(a1[0][0], n)
        product2 = pow(a1[0][1], n)
        product3 = pow(1 - pow(1 - pow(a1[1][0], self.q), n), 1 / self.q)
        product4 = pow(1 - pow(1 - pow(a1[1][1], self.q), n), 1 / self.q)

        a = ([product1, product2], [product3, product4])
        return a

    #区间值广义正交运算法除法
    def Division(self, a1, a2):
        product1 = pow(
            pow(a1[0][0], self.q) + pow(a2[1][0], self.q) - (pow(a1[0][0], self.q)) * (pow(a2[1][0], self.q)),
            1 / self.q)
        product2 = pow(
            pow(a1[0][1], self.q) + pow(a2[1][1], self.q) - (pow(a1[0][1], self.q)) * (pow(a2[1][1], self.q)),
            1 / self.q)
        product3 = a1[1][0] * a2[0][0]
        product4 = a1[1][1] * a2[0][1]
        a = ([product1, product2], [product3, product4])

        return a

    #保留小数
    def dataProcessing(self, A):
        B = ([0, 0], [0, 0])
        for i in range(2):
            for j in range(2):
                B[i][j] = round(A[i][j], 6)
        return B


    def outputMatrix(self,Ma):
        for i in range(len(Ma)):
            for j in range(len(Ma[i])):
                print(Ma[i][j],end='')
            print()

    def outputList(self,ls,title):
        for i in range(len(ls)):
            print(title[i],': ',ls[i])


    def sortIndex(self,Ke,Te):
        '''
        把所有备选方案分值排序，下标也进行排序
        :param Ke:
        :return:
        '''
        for i in range(len(Ke)):
            k = i
            for j in range(i+1, len(Ke)):
                if Ke[k][0] < Ke[j][0]:
                    k = j
                if Ke[k][0] == Ke[j][0]:
                    if Te[Ke[k][1]][0] >= Te[Ke[j][1]][0]:
                        k = k
                    else:
                        k = j
            if k != i:
                t = Ke[i]
                Ke[i] = Ke[k]
                Ke[k] = t
    def get_grade(self,a):
        grade = (pow(a[0][0],self.q)+pow(a[0][1],self.q)-pow(a[1][0],self.q)-pow(a[1][1],self.q))/2

        return grade

    def getScoreMatrix2(self,Ma):
        '''
        得分函数，对模糊集求得分
        :param Ma:
        :return:
        '''
        ls = []
        for i in range(len(Ma)):
            ls.append(round((pow(Ma[i][0][0],self.q)+pow(Ma[i][0][1],self.q)+pow(1-Ma[i][1][0],self.q)+pow(1-Ma[i][1][1],self.q))/2,6))
        return ls

    def getScoreMatrix(self,Ma):
        '''
        得分函数，对模糊集求得分
        :param Ma:
        :return:
        '''
        ls = []
        for i in range(len(Ma)):
            l = []
            l.append(round((pow(Ma[i][0][0],self.q)+pow(Ma[i][0][1],self.q)+pow(1-Ma[i][1][0],self.q)+pow(1-Ma[i][1][1],self.q))/2,6))
            l.append(i)
            ls.append(l)
        return ls

    def getValueMatrix(self,Ma):
        '''
        求准确值
        :param Ma:
        :return:
        '''
        ls = []
        for i in range(len(Ma)):
            l = []
            l.append(round(1/2*(pow(Ma[i][0][0],self.q)+pow(Ma[i][0][1],self.q)+pow(Ma[i][1][0],self.q)+pow(Ma[i][1][1],self.q)),6))
            l.append(i)
            ls.append(l)
        return ls

    #标准化决策矩阵
    def standar(self):
        for i in range(self.lines):
            for j in range(self.colums):
                sum1 = self.power(self.matrix_1[0][j],2)
                for n in range(1,self.lines):
                    a = self.power(self.matrix_1[n][j],2)
                    sum1 = self.Add(sum1,a)
                b = self.power(sum1,1/2)
                self.matrix_1[i][j] = self.Division(self.matrix_1[i][j],b)
        return self.matrix_1

    #比率系统法
    def step(self,m):
        AS = []
        for i in range(self.lines):
            sum1 = self.number_multiplication(m[i][0],self.weight[0])
            for j in range(1, self.colums):
                a = self.number_multiplication(m[i][j],self.weight[j])
                sum1 = self.Add(sum1,a)

            AS.append(sum1)

        return AS


    def getResult(self):
        stander_matrix = self.standar()
        AS = self.step(stander_matrix)
        SM = self.getScoreMatrix(AS)
        SM2 = self.getScoreMatrix2(AS)
        VM = self.getValueMatrix(AS)
        #print('*******每个备选方案得分数值，结果为*******')
        #self.outputList(SM,self.Al_title)
        #print()
        #
        #print('*******每个备选方案精确值，结果为*******')
        #self.outputList(VM,self.Al_title)
        #print()
        #self.sortIndex(SM,VM)
        #print('备选方案排列顺序为(从左到右，由好到差)：')
        #for i in range(len(self.Al_title)):
        #    print(self.Al_title[SM[i][1]], end=' ')
        #print()
        #print('最优备选方案:', self.Al_title[SM[0][1]])
        SM2=[i/sum(SM2) for i in SM2]
        return  SM2


if __name__ == '__main__':
    a1 = [[([0.7, 0.8], [0.2, 0.3]), ([0.5, 0.6], [0.6, 0.7]), ([0.8, 0.9], [0.1, 0.2]), ([0.8, 0.95], [0.1, 0.2])],
          [([0.8, 0.9], [0.1, 0.2]), ([0.5, 0.55], [0.4, 0.5]), ([0.8, 0.9], [0.1, 0.15]), ([0.8, 0.95], [0.1, 0.2])],
          [([0.9, 0.95], [0.1, 0.2]), ([0.5, 0.6], [0.3, 0.4]), ([0.8, 0.85], [0.2, 0.3]), ([0.8, 0.9], [0.1, 0.2])],
          [([0.2, 0.3], [0.7, 0.8]), ([0.4, 0.5], [0.3, 0.4]), ([0.75, 0.8], [0.2, 0.3]), ([0.7, 0.8], [0.2, 0.3])],
          [([0.1, 0.2], [0.8, 0.9]), ([0.2, 0.3], [0.5, 0.6]), ([0.7, 0.85], [0.3, 0.4]), ([0.6, 0.7], [0.2, 0.3])]]
    a=MOORA(a1,[0.25,0.25,0.25,0.25],3)
    print(a.getResult())

